﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Xml;
using System.Text;
using System.Windows.Forms;
using SdmxMl.Manager;
using SdmxMl.Structure;
using SdmxMl.Common;
using SdmxMl.Helper;

namespace SdmxMl.Panels
{
    public partial class DlgSearchAnnotations : Form
    {
        private TreeView tv;
        private SmManager sm;
        private AnnotationLocatorList locList;


        public DlgSearchAnnotations()
        {
            InitializeComponent();

            // Fill combo Artefact types
            foreach (SdmxArtefactType atype in Enum.GetValues(typeof(SdmxArtefactType)))
                comboBoxArtefactType.Items.Add(new ComboArtefactTypeItem(atype));
            comboBoxArtefactType.SelectedIndex = 0; // Default to all

            sm = ReferenceManager.GetSmContainerImage();
        }

        private void dataGridViewRef_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (e.RowIndex >= 0)
                buttonNavigate_Click(sender, EventArgs.Empty);
        }

        private DataRow FindSelectedRow()
        {
            DataRow findRow = null;
            if (dataGridViewResult.DataSource != null)
            {
                BindingManagerBase bm = dataGridViewResult.BindingContext[dataGridViewResult.DataSource, dataGridViewResult.DataMember];
                if (bm.Count > 0)
                    findRow = ((DataRowView)bm.Current).Row;
            }

            return findRow;
        }


        private void buttonNavigate_Click(object sender, EventArgs e)
        {
            try
            {
                DataRow refItem = FindSelectedRow();
                if (refItem != null)
                {
                    // If URN try to get it if not already in memory
                    ArtefactRefTyped art = UrnManager.UrnToArtefactRefTyped(refItem["Reference"].ToString());
                    if (art != null)
                    {
                        UrnParser p = new UrnParser(refItem["Reference"].ToString());

                        // If already in memory, navigate otherwhile get from regidtry
                        if (NavigationManager.LocatenavigateProject(art.Type, art.FullIdent, p) == null)
                            NavigationManager.NavigateWithRegistry(art.Type, art.FullIdent, true, p);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }



        private void buttonSearchRef_Click(object sender, EventArgs e)
        {
            // Create search pattern container, check pattern syntax
            locList = new AnnotationLocatorList(comboBoxAnnotType.Text, textBoxAnnotText.Text, textBoxAnnotTitle.Text, textBoxAnnotUrn.Text);
            /*
            if (locList.IsUndefinedPattern())
            {
                MessageBox.Show("At least one annotation element has to be specified. ", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            */

            tv = ReferenceManager.TreeSdmx;

            // Determines targeted artefact type (if any)
            SdmxArtefactType arType = GetArtefactType();

            // For each artefact container
            foreach (TreeNode nodeContainer in tv.Nodes)
            {  
                // if not empty
                if (nodeContainer.Nodes.Count > 0)
                {
                    // if selected artefact type
                    Artefact a = nodeContainer.Nodes[0].Tag as Artefact;
                    if (a != null && (arType == SdmxArtefactType.None || a.ArType == arType))
                    {
                        SdmxArtefactType actualType = a.ArType;

                        // recurse all nodes
                        foreach (TreeNode ArNode in nodeContainer.Nodes)
                        {
                            Artefact arParent = ArNode.Tag as Artefact;
                            Locate(arParent, ArNode);

                            // Complex artefact has annotations in detail not exposed in tree, manage also BaseDimensionType bdt = null;
                            KeyFamilyType dsd = arParent as KeyFamilyType;
                            if (dsd != null)
                            {
                                foreach (BaseDimensionType bdt in dsd.DimensionList)
                                    LocateForBdt(arParent, bdt);

                                foreach (BaseDimensionType bdt in dsd.CrossSectionalMeasureList)
                                    LocateForBdt(arParent, bdt);

                                foreach (BaseDimensionType bdt in dsd.AttributeList)
                                    LocateForBdt(arParent, bdt);
                            }

                            MetadataStructureDefinitionType msd = arParent as MetadataStructureDefinitionType;
                            if (msd != null)
                            {
                                // Reports
                                foreach (ReportStructureType rpt in msd.ReportStructureList)
                                    foreach (MetadataAttributeType meta in rpt.MetadataAttributeList)
                                        LocateForMeta(arParent, msd, rpt, meta);
                            }

                            HierarchicalCodelistType hclt = arParent as HierarchicalCodelistType;
                            if (hclt != null)
                            {
                                foreach (HierarchyType ht in hclt.HierarchyList)
                                    LocateForHierarchy(arParent, ht);
                            }
                        }
                    }
                }
            }
            dataGridViewResult.DataSource = locList.AsDataTable();
        }

        private void LocateForBdt(Artefact arParent, BaseDimensionType bdt)
        {
            string urn = string.Empty;
            AnnotationList ian = null;
            if (bdt != null)
                ian = bdt.AnnotationList;
            if (ian != null)
            {
                foreach (Annotation ann in ian)
                {
                    if (locList.isCandidate(ann))
                        locList.Add(new AnnotationLocator(ann,
                               UrnManager.FullIdToUrn(arParent.ArType.ToString(), arParent.FullIdent, bdt, null), bdt.ToString()));
                }

            }
        }

        private void LocateForMeta(Artefact arParent, MetadataStructureDefinitionType msd, ReportStructureType rpt, MetadataAttributeType meta)
        {
            string urn = string.Empty;
            AnnotationList ian = null;
            if (meta != null)
                ian = meta.AnnotationList;
            if (ian != null)
            {
                foreach (Annotation ann in ian)
                {
                    if (locList.isCandidate(ann))
                        locList.Add(new AnnotationLocator(ann,
                               UrnManager.FullIdToUrn(arParent.ArType.ToString(), arParent.FullIdent, meta, rpt), meta.ToString()));
                }
            }
        }

        private void LocateForHierarchy(Artefact arParent, HierarchyType ht)
        {
            string urn = string.Empty;
            AnnotationList ian = null;
            if (ht != null)
                ian = ht.AnnotationList;
            if (ian != null)
            {
                foreach (Annotation ann in ian)
                {
                    if (locList.isCandidate(ann))
                        locList.Add(new AnnotationLocator(ann,
                               UrnManager.FullIdToUrn(arParent.ArType.ToString(), arParent.FullIdent, ht, null), ht.ToString()));
                }

            }
        }


        private void Locate(Artefact arParent, TreeNode node)
        {
            IAnnotationList ian = node.Tag as IAnnotationList;
            string urn = string.Empty;
            if (ian != null)
            {
                foreach (Annotation ann in ian.AnnotationList)
                {
                    if (locList.isCandidate(ann))
                    {
                        Artefact a = node.Tag as Artefact;
                        ISdmxHierarchyListItem item =  node.Tag as ISdmxHierarchyListItem;
                        
                        if (a != null)
                            locList.Add(new AnnotationLocator(ann, 
                                UrnManager.FullIdToUrn(a.ArType.ToString(), a.FullIdent, null, null), a.ToString()));
                        else if (item != null)
                            locList.Add(new AnnotationLocator(ann,
                               UrnManager.FullIdToUrn(arParent.ArType.ToString(), arParent.FullIdent, item, null), item.ToString()));
                    }
                }
                
            }
            foreach (TreeNode n in node.Nodes)
                Locate(arParent, n);
        }

        private SdmxArtefactType GetArtefactType()
        {
            if (comboBoxArtefactType.SelectedItem != null)
                return (comboBoxArtefactType.SelectedItem as ComboArtefactTypeItem).ArType;
            return SdmxArtefactType.None;
        }

    }
}
